package com.chenyitun.cloudsystem.security.realm;

import com.chenyitun.cloudcommon.utils.JwtUtils;
import com.chenyitun.cloudsystem.constants.Constants;
import com.chenyitun.cloudsystem.domain.User;
import com.chenyitun.cloudsystem.security.token.JwtToken;
import com.chenyitun.cloudsystem.service.MenuService;
import com.chenyitun.cloudsystem.service.RoleService;
import com.chenyitun.cloudsystem.service.UserService;
import com.chenyitun.cloudsystem.utils.ShiroUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;

@Service
@Qualifier("userRealm")
public class UserRealm extends AuthorizingRealm {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserRealm.class);

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    /**
     * 大坑！，必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        User user = ShiroUtils.getUser();
//        String username = JwtUtils.getUsername(principals.toString());
//        User user = userService.getUser(username);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        // 角色列表
        Set<String> roles = new HashSet<>();
        // 功能列表
        Set<String> menus = new HashSet<>();
        // 管理员拥有所有权限
        if (user.getUserId().toString().equals(Constants.ISADMIN) ){
            simpleAuthorizationInfo.addRole("root");
            simpleAuthorizationInfo.addStringPermission("*:*:*");
        }
        else{
            roles = roleService.selectRoleKeys(user.getUserId());
            menus = menuService.listPerms(user.getUserId());
            // 角色加入AuthorizationInfo认证对象
            simpleAuthorizationInfo.setRoles(roles);
            // 权限加入AuthorizationInfo认证对象
            simpleAuthorizationInfo.setStringPermissions(menus);
        }
        return simpleAuthorizationInfo;
    }

    /**
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String jwtToken = (String) token.getCredentials();
        // 解密获得username，用于和数据库进行对比
        String username = JwtUtils.getUsername(jwtToken);
        if (username == null) {
            throw new AuthenticationException("令牌不合法");
        }
        User user = userService.getUser(username);
        if (user == null) {
            throw new AuthenticationException("用户不存在");
        }
        if (! JwtUtils.verify(jwtToken, username)) {
            throw new AuthenticationException("用户名或密码错误");
        }
        return new SimpleAuthenticationInfo(user, jwtToken, getName());

    }
}
